package util;

import configuration.MyConfiguration;
import http.MyHttpRequest;
import http.MyHttpResponse;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;

/**
 * @author Karl
 * @Date 2023/1/11 - 12:04
 */
public class HttpUtil {

    protected static Charset utf_8 = StandardCharsets.UTF_8;

    protected static String lineSeparator = System.lineSeparator();

    protected static byte[] lineByte = lineSeparator.getBytes(utf_8);

    private HttpUtil(){}

    /**
     * 将response保存到磁盘中
     * @param request 对应的请求报文
     * @param response 对应的响应报文
     * @return 保存成功失败
     */
    public static boolean saveResponseToDisk(MyHttpRequest request, MyHttpResponse response) {
        File fileName = null;
        OutputStream os = null;

        try {
            fileName = new File(MyConfiguration.getFileRoot() + request.getUrl());
            if (!fileName.getParentFile().exists()&&!fileName.getParentFile().mkdirs()) return false;
            os = new FileOutputStream(fileName);
            writeToFile(response,os);
        } catch (IOException e) {
            MyUtil.log("exception : %s %s", e.getClass(), e.getLocalizedMessage());
            return false;
        }finally {
            if (os != null) {
                MyUtil.closeIo(os);
            }
        }
        return true;
    }

    public static boolean needCache(MyHttpResponse response) {
        int status = response.getStatus();

        if (status >= 200 && status < 300 && status != 204) {
            int cacheTime = checkCacheTime(response);
            if (cacheTime >= 0) {
                response.addResponseHeader(MyConfiguration.getCacheExpireHeader(),
                        MyConfiguration.getCacheExpireHeader() + ": " + MyDateUtil.formatGMTStr(cacheTime)+lineSeparator);
                return true;
            }
            if (response.containsHeader("Expires")) {
                String dateStr = response.getResponseHeader("Expires").trim().split(": ")[1];

                try {
                    long l = MyDateUtil.calGapMillTime(dateStr);
                    response.addResponseHeader(MyConfiguration.getCacheExpireHeader(),
                            MyConfiguration.getCacheExpireHeader() + ": " + MyDateUtil.formatGMTStr((int) -l)+lineSeparator);
                    return true;
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            if (response.containsHeader("ETag") || response.containsHeader("Last-Modified")) {
                return true;
            }

        }


        return false;
    }


    /**
     * 解析Cache-Control的内容，查找max-age|s-maxage 返回是否可以保存,可以返回
     *
     * @return 返回缓存的时间，否则返回-1,0表示需要去源服务器确认一下，也可以保存
     */
    private static int checkCacheTime(MyHttpResponse response) {
        String Cache_Control = null;
        int ret = -1;
        if ((Cache_Control = response.getResponseHeader("Cache-Control"))!=null) {
            Cache_Control = Cache_Control.trim();
        } else if ((Cache_Control = response.getResponseHeader("cache-control"))!=null) {
            Cache_Control = Cache_Control.trim();
        } else return -1;
        if (Cache_Control.contains("s-maxage")) {
            String[] split = Cache_Control.split(",\\s*");
            for (String s : split) {
                if (s.contains("s-maxage")) {
                    String[] kv = s.split("=");
                    try {
                        ret = Integer.parseInt(kv[1]);
                        return ret;
                    } catch (NumberFormatException ignore) {

                    }
                }
            }
        }
        if (Cache_Control.contains("max-age")) {
            String[] split = Cache_Control.split(",\\s*");
            for (String s : split) {
                if (s.contains("max-age")) {
                    String[] kv = s.split("=");
                    try {
                        ret = Integer.parseInt(kv[1]);
                        return ret;
                    } catch (NumberFormatException ignore) {

                    }
                }
            }
        }
        if (Cache_Control.contains("no-cache") || Cache_Control.contains("must-revalidate")) return 0;


        return -1;
    }

    public static void writeToFile(MyHttpResponse response,OutputStream file) throws IOException {

        file.write(response.getResponseLine().getBytes());

        for (String header : response.getResponseHeader()) {
//            if(header.contains("Proxy-Cache-Time")){
//                file.write(header.replace("18","10").getBytes());
//            }else if(header.contains("ETag")){
//                file.write(header.replace("435","433").getBytes());
//            }else
            file.write(header.getBytes());
        }
        file.write(lineByte);
        for (Byte aByte : response.getResponseBody()) {
            file.write(aByte);
        }
    }


}
